/* ==================================================================
* Copyright (c) 2024/12/06 SCNU LiuJunJie z-ken
* All rights reserved.
* fileName:	mainwindow.cpp
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the xxx Group. and
* its contributors.
* 4. Neither the name of the Group nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Author,GROUP AND CONTRIBUTORS
* ===================================================================
* Author: LiuJunJie z-ken.
*/

#include "mainwindow.h"
#include "ui_mainwindow.h"

void MainWindow::assignUiPoint()
{
    //## Re的DFA、MinDFA和NFA相关的内容 re页面的第一个Tab-选择文件并且运行得到编码文件
    rePlaintextEdit = ui->rePlaintextEdit;
    openReFile = ui->openReFile;
    reSaveFile = ui->reSaveFile;
    reGenerate = ui->reGenerate;
    reSelectOutputSourceCodePosBtn=ui->reSelectOutputSourceCodePosBtn; // 选择分析器源代码生成位置按钮
    reCreateFile=ui->reCreateFile; // 创建文件按钮
    reGenerateCodeTextEdit = ui->reGenerateCodeTextEdit;

    // re中第二个Tab栏相关的按钮
    reOpenSelectSourceFileCodeBtn = ui->reOpenSelectSourceFileCodeBtn;// 打开需要编码的文件按钮
    //    QString selectSourceCodePath=""; // 选择源代码的路径
    reCompileSourceCodeBtn = ui->reCompileSourceCodeBtn;// 执行编译，编译选择的代码按钮
    reEncodingFilePathBtn = ui->reEncodingFilePathBtn ;// 编码文件输出位置获取按钮
    reGenerateTokenTypeBtn  = ui->reGenerateTokenTypeBtn;// 执行代码，生成编码文件按钮
    reSelectOrignFileBtn = ui->reSelectOrignFileBtn;// 选择需要被分析的文件
    reSelectOutputExePathBtn = ui->reSelectOutputExePathBtn; // 选择Exe生成的位置按钮


    saveAnalyedFileChangeBtn = ui->saveAnalyedFileChangeBtn; // 保存对分析文件的修改按钮
    saveEncodedFileChangeBtn = ui->saveEncodedFileChangeBtn; // 保存对编码文件的修改按钮


    // -- 文本窗口
    reUserSelectGenerateCodeTextEdit = ui->reUserSelectGenerateCodeTextEdit; // 用户打开的文本文件
    reEncodingFileContentEdit = ui->reEncodingFileContentEdit; // 打开的编码文件显示的Edit
    reAnalyzedOriginFileEdit  = ui->reAnalyzedOriginFileEdit; // 选择的需要被分析的Edit编辑窗口


    // NFA和DFA的tabWidit
    tabWidgitReNFA = ui->tabWidgitReNFA;
    tabWidgitReDFA = ui->tabWidgitReDFA;
    tabWidgitReMinDFA = ui->tabWidgitReMinDFA;

    // ## LALR工具的内容，对应顶层的Tab2的节点

    lalrOpenFile = ui->lalrOpenFile ;
    lalrGenerate = ui-> lalrGenerate ;
    lalrSaveFile = ui->lalrSaveFile ;
    lalrProductionTextEdit  = ui->lalrProductionTextEdit;
    productionsTable = ui->productionsTable;
    firstSetTable = ui->firstSetWidget;
    followSetTable = ui->followSetWidget;
    LR_DFA_Table = ui->LR_DFA_table;
    LR_DFA_item_Table = ui->LR_DFA_item_table;
    LALR_DFA_Table = ui->LALR_DFA_table;
    LALR_DFA_item_WidgetTable = ui->LALR_DFA_item_table;
    analyseSheetTable = ui->analyseSheetTable;


    // lalr的tab2部分内容
    lalrEncodedFileTextEdit= ui->lalrEncodedFileTextEdit; // 编码文件展示框
    lalrJointFileSourceCodeEdit= ui->lalrJointFileSourceCodeEdit; // 分析器源代码文本框
    lalrOriginFileEdit = ui->lalrOriginFileEdit ; // 未编码文件文本框
    lalrOpenEncodedFileBtn= ui->lalrOpenEncodedFileBtn; // 打开编码文件
    lalrOpenJointFileBtn= ui->lalrOpenJointFileBtn; // 打开分析器文件
    lalrOpenOriginFileBtn= ui->lalrOpenOriginFileBtn; // 打开未编码文件

    lalrProcessByEncodedFileBtn = ui->lalrProcessByEncodedFileBtn; // 使用编码文件执行分析
    lalrProcessByJointFileAndOriginFileBtn = ui->lalrProcessByJointFileAndOriginFileBtn; // 使用分析器和未编码文件进行分析

    // 分析记录和分析树
    atrributeNameBox = ui->atrributeNameBox;
     lalrAnalyseRecordTableWidget=ui->lalrAnalyseRecordTableWidget;
     lalrAstTreeWidget=ui->lalrAstTreeWidget;
     lalrAnalyseTreeWidget=ui->lalrAnalyseTreeWidget;
}



MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->resize(1000,800);
    //    ui->tabWidget->addTab(new QWidget(),"asd");
    //    ui->tabWidget->clear();
    assignUiPoint();
    reItemBuild();

}

MainWindow::~MainWindow()
{
    delete ui;
}



void MainWindow::reItemBuild()
{
    connectEventRe_Tab_1();
    connectEventRe_Tab_2();
    connectEventLalr_Tab_1();
    connectEventLalr_Tab_2();
}

void MainWindow::connectEventRe_Tab_1()
{
    // 保存文件
    connect(reSaveFile,&QPushButton::clicked,[=]{
        // 当文本发生变化时，将变化后的内容写入目标文件中
        // 检测文件路径不为空
        if (!reFilePath.isEmpty()) {
            QFile file(reFilePath);
            if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
                QTextStream out(&file);
                out << rePlaintextEdit->toPlainText();
                file.close();
                QMessageBox::information(this, tr("Success"), tr("保存成功"));
            } else {
                QMessageBox::warning(this, tr("Error"), tr("你需要打开一个文件才能进行保存;Failed to open file for saving!"));
            }
        }
        else
        {
            QMessageBox::warning(this, tr("Error"), tr("你需要打开一个文件才能进行保存;No file has open for saving!"));
        }
    });

    // 打开文件
    QObject::connect(openReFile, &QPushButton::clicked, [&]() {
        QFileDialog fileDialog ;
        fileDialog.setDefaultSuffix("./");
        QString dialogFilePath= fileDialog.getOpenFileName(this, "Open File", "", "All Files (*.*) ;; Text Files (*.txt)");
        //        qDebug()<<fileDialog.getExistingDirectory(this); // 选择文件夹
        if(dialogFilePath.isEmpty() == false)
        {
            reFilePath = dialogFilePath;
        }
        if (!reFilePath.isEmpty()) {
            QFile file(reFilePath);
            if (file.open(QIODevice::ReadOnly)) {
                QTextStream in(&file);
                // 必须要设置解码器 -- utf-8支持
                in.setCodec(codec);
                QString res = in.readAll();
                qDebug()<<res;
                rePlaintextEdit->setPlainText(res);
                file.close();
            }
        }
    });

    // 选择输出文件代码的位置
    QObject::connect(reSelectOutputSourceCodePosBtn, &QPushButton::clicked, [&]() {
        QFileDialog fileDialog ;
        fileDialog.setDefaultSuffix("./");
        QString dialogFilePath= fileDialog.getOpenFileName(this, "Open File", "", "All Files (*.*) ;; Text Files (*.txt)");
        if(dialogFilePath.isEmpty() == false)
        {
            reOutputSourceCodePath = dialogFilePath;
            QMessageBox::information(nullptr, ("Success"), ("文件选择成功"));

            QFile file(reOutputSourceCodePath);
            if (file.open(QIODevice::ReadOnly)) {
                QTextStream in(&file);
                // 必须要设置解码器 -- utf-8支持
                in.setCodec(codec);
                QString res = in.readAll();
                qDebug()<<res;
                reGenerateCodeTextEdit->setPlainText(res);
                file.close();
            }
        }
        else
        {
            QMessageBox::warning(nullptr, ("Error"), ("选择失败，你选择了空的文件夹!"));
        }
    });

    // 创建文件
    QObject::connect(reCreateFile, &QPushButton::clicked, [&](){
        QFileDialog fileDialog;
        fileDialog.setAcceptMode(QFileDialog::AcceptSave);
        fileDialog.setDefaultSuffix("txt"); // 设置默认文件后缀
        QString createFileName = fileDialog.getSaveFileName(this, ("创建文件"), QString(), ("Text Files (*.txt) ;; CPP Files (*.cpp) ;; TNY Files (*.tny) ;; LEX Files (*.lex)"));

        if (!createFileName.isEmpty()) {
            // 尝试创建并写入文件
            QFile file(createFileName);
            if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
                QTextStream out(&file);
                out << "Hello, this is a test file." << endl;
                file.close();
                QMessageBox::information(nullptr, ("Success"), ("文件创建成功"));
            } else {
                QMessageBox::warning(nullptr, ("Error"), ("Cannot write to file!"));
            }
        }
    });

    // 代码生成
    QObject::connect(reGenerate, &QPushButton::clicked, [&](){
        GenerateReNfaDfaAndShow();
    });
}



void MainWindow::connectEventRe_Tab_2()
{
    //    QPlainTextEdit* reUserGenerateCodeTextEdit; // 用户打开的文本文件
    //    QPlainTextEdit*  reEncodingFileContentEdit; // 打开的编码文件显示的Edit

    //    QPushButton *  reOpenSelectSourceFileCodeBtn;// 打开需要编码的文件按钮
    //    QString reSelectedSourceCodePath=""; // 选择源代码的路径
    // 打开源代码文件
    QObject::connect(reOpenSelectSourceFileCodeBtn, &QPushButton::clicked, [&]() {
        QFileDialog fileDialog ;
        fileDialog.setDefaultSuffix("./");
        QString dialogFilePath= fileDialog.getOpenFileName(this, "Open File", "", "All Files (*.*) ;; Text Files (*.cpp)");
        //        qDebug()<<fileDialog.getExistingDirectory(this); // 选择文件夹
        if(dialogFilePath.isEmpty() == false)
        {
            reSelectedSourceCodePath = dialogFilePath;
        }
        else
        {
            QMessageBox::warning(nullptr, ("Error"), ("你未成功选择分析器的源代码文件"));
        }
        if (!reSelectedSourceCodePath.isEmpty()) {
            QFile file(reSelectedSourceCodePath);
            if (file.open(QIODevice::ReadOnly)) {
                QTextStream in(&file);
                // 必须要设置解码器 -- utf-8支持
                in.setCodec(codec);
                QString res = in.readAll();
                qDebug()<<res;
                reUserSelectGenerateCodeTextEdit->setPlainText(res);
                file.close();
            }
        }
    });

    //绑定按钮
    //    QPushButton * reCompileSourceCodeBtn;// 执行编译，编译选择的代码按钮
    QObject::connect(reCompileSourceCodeBtn, &QPushButton::clicked, [&](){
        // 编码文件位置判断
        if (reSelectedSourceCodePath.isEmpty()) {
            QMessageBox::warning(nullptr, ("Error"), ("你未成功选择分析器的源代码文件"));
            return;
        }
//        // exe文件位置判断
//        if (reOutPutJointExePath.isEmpty()) {
//            QMessageBox::warning(nullptr, ("Error"), ("未选择：分析器需要生成的文件夹位置"));
//            return;
//        }
        // 执行编译
//        this->reToDfaAlgor.complieCppFile(reSelectedSourceCodePath.toStdString(),reOutPutJointExePath.toStdString());
        if(reOutPutJointExePath.isEmpty())
        {
            reOutPutJointExePath=QString::fromStdString(reToDfaAlgor.exeFileDefualtPath);
            this->reToDfaAlgor.complieCppFile(reSelectedSourceCodePath.toStdString());
        }
        else
        {
            this->reToDfaAlgor.complieCppFile(string(reSelectedSourceCodePath.toLocal8Bit()),string(reOutPutJointExePath.toLocal8Bit()));
        }

        QMessageBox::information(nullptr, ("Success"), ("操作成功"));
    });

    // 绑定按钮
    //    QPushButton * reSelectOutputExePathBtn;// 编码文件输出位置获取按钮
    //    QString reOutPutJointExePath="";// 输出可执行文件的位置
    QObject::connect(reSelectOutputExePathBtn, &QPushButton::clicked, [&](){
        // 打开选择文件夹的对话框
        QFileDialog fileDialog;
        fileDialog.setAcceptMode(QFileDialog::AcceptSave);
        fileDialog.setDefaultSuffix("txt"); // 设置默认文件后缀
        QString fileName = fileDialog.getSaveFileName(nullptr, ("选择你要需要生成的文件路径"), QString(), ("EXE Files (*.exe)"));
        qDebug()<<fileName ;
        if (!fileName.isEmpty()) {
            reOutPutJointExePath = fileName;
            QMessageBox::information(nullptr, ("Success"), ("操作成功"));
        }
        else
        {
            QMessageBox::warning(nullptr, ("Error"), ("未选择成功：分析器需要生成的文件夹位置"));
        }
    });


    // 需要分析器文件
    //    QPushButton * reSelectOrignFileBtn;// 选择需要被分析的文件
    //    QString reAnalysedOrignFilePath="";
    // 选择打开需要进行分析的文件
    QObject::connect(reSelectOrignFileBtn, &QPushButton::clicked, [&]() {
        QFileDialog fileDialog ;
        fileDialog.setDefaultSuffix("./");
        QString dialogFilePath= fileDialog.getOpenFileName(this, "选择需要被分析的文件", "", "All Files (*.*) ;;  Tiny Files (*.tny) ;; Text Files (*.txt)");
        if(dialogFilePath.isEmpty() == false)
        {
            reAnalysedOrignFilePath = dialogFilePath;
             QMessageBox::information(nullptr, ("Success"), ("操作成功"));
        }
        else
        {
            QMessageBox::warning(nullptr, ("Error"), ("你未成功选择分析器的源代码文件"));
        }
        if (!reAnalysedOrignFilePath.isEmpty()) {
            QFile file(reAnalysedOrignFilePath);
            if (file.open(QIODevice::ReadOnly)) {
                QTextStream in(&file);
                // 必须要设置解码器 -- utf-8支持
                in.setCodec(codec);
                QString res = in.readAll();
                qDebug()<<res;
                reAnalyzedOriginFileEdit->setPlainText(res);
                file.close();
            }
        }
    });


//    QPushButton *  saveAnalyedFileChangeBtn; // 保存对分析文件的修改按钮
    QObject::connect(saveAnalyedFileChangeBtn, &QPushButton::clicked, [&]() {
        // 当文本发生变化时，将变化后的内容写入目标文件中
        // 检测文件路径不为空
        if (!reAnalysedOrignFilePath.isEmpty()) {
            QFile file(reAnalysedOrignFilePath);
            if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
                QTextStream out(&file);
                out << this->reAnalyzedOriginFileEdit->toPlainText();
                file.close();
                QMessageBox::information(this, tr("Success"), tr("保存成功"));
            } else {
                QMessageBox::warning(this, tr("Error"), tr("保存时刻发生错误，你需要保证文件性质可读等条件"));
            }
        }
        else
        {
            QMessageBox::warning(this, tr("Error"), tr("你需要打开一个文件才能进行保存;No file has open for saving!"));
        }
    });

//    QPushButton *  saveEncodedFileChangeBtn; // 保存对编码文件的修改按钮
    QObject::connect(saveEncodedFileChangeBtn, &QPushButton::clicked, [&]() {
        // 当文本发生变化时，将变化后的内容写入目标文件中
        // 检测文件路径不为空
        if (!reEncodingFilePath.isEmpty()) {
            QFile file(reEncodingFilePath);
            if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
                QTextStream out(&file);
                out << this->reEncodingFileContentEdit->toPlainText();
                file.close();
                QMessageBox::information(this, tr("Success"), tr("保存成功"));
            } else {
                QMessageBox::warning(this, tr("Error"), tr("保存时刻发生错误，你需要保证文件性质可读等条件"));
            }
        }
        else
        {
            QMessageBox::warning(this, tr("Error"), tr("你需要打开一个文件才能进行保存;No file has open for saving!"));
        }
    });

    //    QPushButton * reEncodingFilePathBtn;// 选择文件被分析后的分析结果位置
//        QString reEncodingFilePath="";
    QObject::connect(reEncodingFilePathBtn, &QPushButton::clicked, [&]() {
        QFileDialog fileDialog ;
        QString dialogFilePath= fileDialog.getOpenFileName(this, "选择需要保存的文件编码文件位置", "", "All Files (*.*) ;;  Tiny Files (*.tny) ;; Text Files (*.txt)");
        if(dialogFilePath.isEmpty() == false)
        {
            reEncodingFilePath = dialogFilePath;
            QMessageBox::information(nullptr, ("Success"), ("操作成功"));
        }
        else
        {
            QMessageBox::warning(nullptr, ("Error"), ("你未成功选择保存编码文件的位置"));
        }
        if (!reEncodingFilePath.isEmpty()) {
            QFile file(reEncodingFilePath);
            if (file.open(QIODevice::ReadOnly)) {
                QTextStream in(&file);
                // 必须要设置解码器 -- utf-8支持
                in.setCodec(codec);
                QString res = in.readAll();
                qDebug()<<res;
                reEncodingFileContentEdit->setPlainText(res);
                file.close();
            }
        }
    });

    //    QPushButton * reGenerateTokenTypeBtn ;// 执行代码，生成编码文件按钮
    QObject::connect(reGenerateTokenTypeBtn, &QPushButton::clicked, [&](){

        if(reOutPutJointExePath.isEmpty())
        {
            QMessageBox::warning(this,"警告","你未选择分析器EXE程序或者未还未进行编译");
            return;
        }


        if(reAnalysedOrignFilePath.isEmpty())
        {
            QMessageBox::warning(this,"警告","你未选择需要被编码的原始文件");
            return;
        }

        if(reEncodingFilePath.isEmpty())
        {
            QMessageBox::warning(this,"警告","你未选择编码文件的存放位置");
            return;
        }

        // 进行文件进行编码
        //        reToDfaAlgor.useJointExe(reOutPutJointExePath.toStdString(),reAnalysedOrignFilePath.toStdString(),reEncodingFilePath.toStdString());
        reToDfaAlgor.useJointExe(string(reOutPutJointExePath.toLocal8Bit()),string(reAnalysedOrignFilePath.toLocal8Bit()),string(reEncodingFilePath.toLocal8Bit()));
        // 将窗口显示的编码文件更新
        if (!reEncodingFilePath.isEmpty()) {
            QFile file(reEncodingFilePath);
            if (file.open(QIODevice::ReadOnly)) {
                QTextStream in(&file);
                // 必须要设置解码器 -- utf-8支持
                in.setCodec(codec);
                QString res = in.readAll();
                qDebug()<<res;
                reEncodingFileContentEdit->setPlainText(res);
                file.close();
            }
        }
    });


}

void MainWindow::processAttributeNameBox()
{
    if(ui->atrributeNameBox->currentIndex()==0)
    {
        this->lalrAlgor.setOnlyUseConfigAst(true);
    }
    else
    {
        this->lalrAlgor.setOnlyUseConfigAst(false);
    }
}

void MainWindow::connectEventLalr_Tab_1()
{

//    lalrOpenFile = ui->lalrOpenFile ;
//    lalrGenerate = ui-> lalrGenerate ;
//    lalrSaveFile = ui->lalrSaveFile ;
//    lalrProductionTextEdit  = ui->lalrProductionTextEdit;
//    productionsTable = ui->productionsTable;
//    firstSetTable = ui->firstSetWidget;
//    followSetTable = ui->followSetWidget;
//    LR_DFA_Table = ui->LR_DFA_table;
//    LR_DFA_item_Table = ui->LR_DFA_item_table;
//    LALR_DFA_Table = ui->LALR_DFA_table;
//    LALR_DFA_item_WidgetTable = ui->LALR_DFA_item_table;
//    analyseSheetTable = ui->analyseSheetTable;


    // 保存文件
    connect(lalrSaveFile,&QPushButton::clicked,[=]{
        // 当文本发生变化时，将变化后的内容写入目标文件中
        if (!productionFilePath.isEmpty()) {
            QFile file(productionFilePath);
            if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
                QTextStream out(&file);
                out << lalrProductionTextEdit->toPlainText();
                file.close();
            } else {
                QMessageBox::warning(this, tr("Error"), tr("你需要打开一个文件才能进行保存;Failed to open file for saving!"));
            }
        }
        else
        {
            QMessageBox::warning(this, tr("Error"), tr("你需要打开一个文件才能进行保存;No file has open for saving!"));
        }
    });


    // 打开文件
    QObject::connect(lalrOpenFile, &QPushButton::clicked, [&]() {
        QFileDialog fileDialog ;
        fileDialog.setDefaultSuffix("./");
        QString dialogFilePath = fileDialog.getOpenFileName(this, "Open File", "", "All Files (*.*) ;; Text Files (*.txt)");

        if(dialogFilePath.isEmpty() == false)
        {
            productionFilePath = dialogFilePath;
        }
        if (!productionFilePath.isEmpty()) {
            QFile file(productionFilePath);
            if (file.open(QIODevice::ReadOnly)) {
                QTextStream in(&file);
                // 必须要设置解码器
                in.setCodec(codec);
                QString res = in.readAll();
                qDebug()<<res;
                lalrProductionTextEdit->setPlainText(res);
                file.close();
            }
        }
    });


    QObject::connect(lalrGenerate, &QPushButton::clicked, [&]() {

        try {
            // 如果文法文件为
            if(productionFilePath.isEmpty())
            {
                QMessageBox::warning(this, tr("Error"), tr("你需要打开一个文件才能进行生成;No file has open to generate!"));
                return ;
            }
            // 如果配置文件为空
            if(lalrAlgor.isOnlyUseConfigAst()&& this->lalrAttrbuteFilePath.isEmpty())
            {
                QMessageBox::warning(this, tr("Error"), tr("你需要打开一个配置文件才能进行生成！！"));
                return;
            }
            generateLalrAndShow();
        }
        catch(PRODUCTIONS_SENTENCE_ERROR)
        {
            QString msg = QString::fromStdString(PRODUCTIONS_SENTENCE_ERROR().message);
            QMessageBox::warning(this, tr("Error"),msg);
        }
        catch (...) {
            QString msg = QString("Unknow 发生了未知的错误");
            QMessageBox::warning(this, tr("Error"),msg);
        }
    });

    // 配置文件选择按钮
    QObject::connect(ui->lalrAttrConfigFileBtn, &QPushButton::clicked,[&](){
        this->lalrAttrbuteFilePath =DialogUtil().getFilePath(ui->lalrAttrConfigFileTextEdit);
        this->lalrAlgor.setAttributeConfigFile(string(lalrAttrbuteFilePath.toLocal8Bit()));
    });
}


void MainWindow::connectEventLalr_Tab_2()
{
    // 类内指向ui的指针遍历如下注释中，方便快速查看
//    QPlainTextEdit* lalrEncodedFileTextEdit; // 编码文件展示框
//    QString lalrEncodedFilePath;
//    QPlainTextEdit* lalrJointFileSourceCodeEdit; // 分析器源代码文本框
//    QString lalrJointFileSourceCodePath;
//    QPlainTextEdit* lalrOriginFileEdit ; // 未编码文件文本框
//    QString lalrOriginFilePath;
//    QPushButton* lalrOpenEncodedFileBtn; // 打开编码文件
//    QPushButton* lalrOpenJointFileBtn; // 打开分析器文件
//    QPushButton* lalrOpenOriginFileBtn; // 打开未编码文件

//    QPushButton* lalrProcessByEncodedFileBtn; // 使用编码文件执行分析
//    QPushButton* lalrProcessByJointFileAndOriginFileBtn; // 使用分析器和未编码文件进行分析

// ## 进行
    // QPushButton* lalrOpenEncodedFileBtn; // 打开编码文件
    // 打开文件
    QObject::connect(lalrOpenEncodedFileBtn, &QPushButton::clicked, [&]() {
        QFileDialog fileDialog ;
        QString dialogFilePath = fileDialog.getOpenFileName(this, "打开一个编码文件", "", "All Files (*.*) ;; Text Files (*.lex) ;; Text Files (*.txt)");

        if(dialogFilePath.isEmpty() == false)
        {
            lalrEncodedFilePath = dialogFilePath;
        }
        if (!lalrEncodedFilePath.isEmpty()) {
            QFile file(lalrEncodedFilePath);
            if (file.open(QIODevice::ReadOnly)) {
                QTextStream in(&file);
                // 必须要设置解码器
                in.setCodec(codec);
                QString res = in.readAll();
                qDebug()<<res;
                lalrEncodedFileTextEdit->setPlainText(res);
                file.close();
            }
        }
    });

//    QPushButton* lalrOpenJointFileBtn; // 打开分析器文件
    QObject::connect(lalrOpenJointFileBtn, &QPushButton::clicked, [&]() {
        QFileDialog fileDialog ;
        QString dialogFilePath = fileDialog.getOpenFileName(this, "打开一个编码文件", "", "All Files (*.*) ;; Text Files (*.lex) ;; Text Files (*.txt)");

        if(dialogFilePath.isEmpty() == false)
        {
            lalrJointFileSourceCodePath = dialogFilePath;
        }
        if (!lalrJointFileSourceCodePath.isEmpty()) {
            QFile file(lalrJointFileSourceCodePath);
            if (file.open(QIODevice::ReadOnly)) {
                QTextStream in(&file);
                // 必须要设置解码器
                in.setCodec(codec);
                QString res = in.readAll();
                qDebug()<<res;
                lalrJointFileSourceCodeEdit->setPlainText(res);
                file.close();
            }
        }
    });

//    QPushButton* lalrOpenOriginFileBtn; // 打开未编码文件
    QObject::connect(lalrOpenOriginFileBtn, &QPushButton::clicked, [&]() {
        QFileDialog fileDialog ;
        QString dialogFilePath = fileDialog.getOpenFileName(this, "打开一个编码文件", "", "All Files (*.*) ;; Text Files (*.lex) ;; Text Files (*.txt)");

        if(dialogFilePath.isEmpty() == false)
        {
            lalrOriginFilePath = dialogFilePath;
        }
        if (!lalrOriginFilePath.isEmpty()) {
            QFile file(lalrOriginFilePath);
            if (file.open(QIODevice::ReadOnly)) {
                QTextStream in(&file);
                // 必须要设置解码器
                in.setCodec(codec);
                QString res = in.readAll();
                qDebug()<<res;
                lalrOriginFileEdit->setPlainText(res);
                file.close();
            }
        }
    });

//    QPushButton* lalrProcessByEncodedFileBtn; // 使用编码文件执行分析
    QObject::connect(lalrProcessByEncodedFileBtn, &QPushButton::clicked, [&]() {
            // 如果编码文件为空
        if (lalrEncodedFilePath.isEmpty())
        {
            QMessageBox::warning(this, tr("Error"), tr("你需要打开一个文件才能进行生成！"));
        }
        else
        {
            try{
                // TODO 执行算法函数并且渲染树
                lalrAlgor.processAnalyseProgramByEncodingFile(string(lalrEncodedFilePath.toLocal8Bit()));
                buildAnalyseRecord_Ast_AnalyseTree();
                 QMessageBox::information(this,"Success","生成成功");
            }catch(...)
            {
                QMessageBox::warning(this,"警告！","分析时刻发生错误，你需要检查你的属性文法名称是否正确选择");
            }
        }

    });
//    QPushButton* lalrProcessByJointFileAndOriginFileBtn; // 使用分析器和未编码文件进行分析
    QObject::connect(lalrProcessByJointFileAndOriginFileBtn, &QPushButton::clicked, [&]() {
        // 如果分析器代码文件为空
        if (lalrJointFileSourceCodePath.isEmpty())
        {
            QMessageBox::warning(this, tr("Error"), tr("你需要打开一个分析器文件才能进行生成！"));
            return ;
        }
        // 如果未编码文件为空
        if (lalrOriginFilePath.isEmpty())
        {
            QMessageBox::warning(this, tr("Error"), tr("你还没有打开未进行编码的文件"));
            return ;
        }
        try{

            // 临时储存分析结果
            int analyesState = true;
            // 执行线程和等待窗口
            LalrWorker *worker = new LalrWorker();
            QProgressDialog *progressDialog = new QProgressDialog("你可能需要等待几秒，Please wait...", "Cancel", 0, 0,nullptr);
            progressDialog->setWindowModality(Qt::WindowModal);
//            QObject::connect(worker, &LalrWorker::progress, progressDialog, &QProgressDialog::setValue);
            QObject::connect(worker, &LalrWorker::finished, progressDialog, &QProgressDialog::accept);
            QObject::connect(worker, &LalrWorker::failed,[&](){
                progressDialog->accept();
                analyesState = false;
            });
            QObject::connect(progressDialog, &QProgressDialog::canceled, worker, &LalrWorker::terminate);
            // 执行任务
            QObject::connect(worker, &QThread::started, [&]() {

                try {
                    // 调用算法执行
                    QCoreApplication::processEvents();
//                    lalrAlgor.processAnalyseProgramByAnalyser(lalrOriginFilePath.toStdString(),lalrJointFileSourceCodePath.toStdString());
                    lalrAlgor.processAnalyseProgramByAnalyser(string(lalrOriginFilePath.toLocal8Bit()),string(lalrJointFileSourceCodePath.toLocal8Bit()));

                    QCoreApplication::processEvents();
                    emit worker->finished();
                }
                catch(ANALYSE_ERROR& e)
                {
                    emit worker->failed();
                }
                catch (...) {
                    emit worker->failed();
                }

            });

            worker->start();
            progressDialog->exec();

            // 渲染数据
            buildAnalyseRecord_Ast_AnalyseTree();
            if(analyesState)
            {
                QMessageBox::information(this,"Information","操作成功！");
            }
            else
            {
                QMessageBox::information(this,"Information","分析失败！");
            }

        }catch(...)
        {
            QMessageBox::warning(this,"警告！","分析时刻发生错误，你需要检查你的属性文法名称是否正确选择");
        }
    });
}



void MainWindow::GenerateReNfaDfaAndShow()
{
    if (reFilePath.isEmpty()) {
        QMessageBox::warning(this, tr("Error"), tr("你需要打开一个文件才能进行保存;No file has open for saving!"));
        return;
    }

    // 打开弹窗 -- 弃用
    //    WaitDialog dialog = new WaitDialog(this);
    //    dialog.show();
    //    QCoreApplication::processEvents();  // 保证UI刷新
    // 执行线程和等待窗口
    ReWorker *worker = new ReWorker();
    QProgressDialog *progressDialog = new QProgressDialog("你可能需要等待几秒，Please wait...", "Cancel", 0, 0, this);
    progressDialog->setWindowModality(Qt::WindowModal);
    QObject::connect(worker, &ReWorker::progress, progressDialog, &QProgressDialog::setValue);
    QObject::connect(worker, &ReWorker::finished, progressDialog, &QProgressDialog::accept);
    QObject::connect(progressDialog, &QProgressDialog::canceled, worker, &ReWorker::terminate);

    // 执行任务
    this->reToDfaAlgor = ReToDfaAlgor();
    //    this->reToDfaAlgor.makeIt(reFilePath.toStdString());
    QObject::connect(worker, &QThread::started, [&]() {
        // 调用算法执行
        QCoreApplication::processEvents();
        if(reOutputSourceCodePath.size()==0)
        {
//            this->reToDfaAlgor.makeItWithJointPath(reFilePath.toStdString(), reToDfaAlgor.jointFileDefualtPath);
            this->reToDfaAlgor.makeItWithJointPath(string(reFilePath.toLocal8Bit()),reToDfaAlgor.jointFileDefualtPath);
            // 记录默认文件位置
            this->reOutputSourceCodePath = QString::fromStdString(reToDfaAlgor.jointFileDefualtPath);
        }else
        {
//            this->reToDfaAlgor.makeItWithJointPath(reFilePath.toStdString(),reOutputSourceCodePath.toStdString());
            this->reToDfaAlgor.makeItWithJointPath(string(reFilePath.toLocal8Bit()),string(reOutputSourceCodePath.toLocal8Bit()));
        }

        emit finished();
    });

    worker->start();
    progressDialog->exec();

    qDebug()<<"over it";
    // 显示输出的编码文件
    buildJointFileSourceCodeEdit();
    buildReDfaTableWidgit();
}


void MainWindow::buildJointFileSourceCodeEdit()
{
    if (!reOutputSourceCodePath.isEmpty()) {
        QFile file(reOutputSourceCodePath);
        if (file.open(QIODevice::ReadOnly)) {
            QTextStream in(&file);
            // 必须要设置解码器 -- utf-8支持
            in.setCodec(codec);
            QString res = in.readAll();
            qDebug()<<res;
            reGenerateCodeTextEdit->setPlainText(res);
            file.close();
        }
    }
    else{
        QMessageBox::warning(nullptr, ("Error"), ("暂时为发现用户选择了一个编码文件"));
    }
}

void MainWindow::buildReDfaTableWidgit()
{
    vector<string> reNames;
    tabWidgitReNFA->clear();
    tabWidgitReDFA->clear();
    tabWidgitReMinDFA->clear();
    std::cout<<"start buildReDfaTableWidgit"<<std::endl;

    const NfaDfaRecord &record = reToDfaAlgor.nfaDfaRecord;
        // NFA
    for(int i=0; i<record.NFA_s_record.size();i++ )
    {
        QWidget * addWidget = new QWidget();
        QGridLayout * layout = new QGridLayout;
        QTableWidget *tableWidgit = new QTableWidget();
        layout->addWidget(tableWidgit);
        addWidget->setLayout(layout);
        QString tabName = QString::fromStdString(record.NFA_s_record[i].reTokenName);
        reNames.push_back(record.NFA_s_record[i].reTokenName);
        this->tabWidgitReNFA->addTab(addWidget,tabName);
        // 构建
        setNFA(tableWidgit,record.NFA_s_record[i]);

    }

    // DFA
    for(int i=0; i<record.stateDFA_s.size();i++ )
    {
        QWidget * addWidget = new QWidget();
        QGridLayout * layout = new QGridLayout;
        QTableWidget *tableWidgit = new QTableWidget();
        layout->addWidget(tableWidgit);
        addWidget->setLayout(layout);
        QString tabName = QString::fromStdString(reNames[i]);
        this->tabWidgitReDFA->addTab(addWidget,tabName);
        // 构建
        setDFA(tableWidgit,record.stateDFA_s[i]);
    }
    // MinDFA
    for(int i=0; i<record.minStateDFA_s.size();i++ )
    {
        QWidget * addWidget = new QWidget();
        QGridLayout * layout = new QGridLayout;
        QTableWidget *tableWidgit = new QTableWidget();
        layout->addWidget(tableWidgit);
        addWidget->setLayout(layout);
        QString tabName = QString::fromStdString(reNames[i]);
        this->tabWidgitReMinDFA->addTab(addWidget,tabName);
        // 构建
        setDFA(tableWidgit,record.minStateDFA_s[i]);
    }
}



void MainWindow::setNFA(QTableWidget * tableWidgit, const NfaRecord& nfaRecord)
{
    tableWidgit->setColumnCount(nfaRecord.resualt.size());
    tableWidgit->setRowCount(nfaRecord.NFA2_node_number - 1);// 因为NFA2_node_number从0开始，并且数目为节点个数+1
    // 设置表头
    QStringList headers;
    for(int i=0;i<tableWidgit->columnCount();i++)
    {
        headers.push_back(QString::fromStdString(nfaRecord.resualt[i].regular_Expression));
    }
    tableWidgit->setHorizontalHeaderLabels(headers);

    QStringList rowTags;
    for(int i =0 ;i<tableWidgit->rowCount();i++)
    {
        QString stemp = QString("Row %1").arg(i+1);
        rowTags.push_back(stemp);
    }
    tableWidgit->setVerticalHeaderLabels(rowTags);

    for(int i=1;i<nfaRecord.NFA2_node_number;i++) // 格式定义NFA从1行开始访问
    {
        for(int j=0;j<nfaRecord.resualt.size();j++)
        {
            QTableWidgetItem *item = new QTableWidgetItem(QString::fromStdString(NfaDfaRecordUtil::vectorToString(nfaRecord.NFA[i][j])));
            tableWidgit->setItem(i - 1, j, item);
        }
        if(nfaRecord.nfa_start == i)
        {
            QString stemp = QString("Row %1").arg(i)+":起点";
            rowTags[i-1] = stemp;
            tableWidgit->setVerticalHeaderLabels(rowTags);
        }
        if(nfaRecord.nfa_end == i)
        {
            QString stemp = QString("Row %1").arg(i)+":终点";
            rowTags[i-1] = stemp;
            tableWidgit->setVerticalHeaderLabels(rowTags);
        }
    }
}

void MainWindow::setDFA(QTableWidget * tableWidgit, const DfaRecord& dfaRecord)
{
    tableWidgit->setColumnCount(dfaRecord.baseState.size());
    tableWidgit->setRowCount(dfaRecord.state_DFA.size());
    // 设置表头
    QStringList headers;
    headers.push_back("当前状态");
    for(int i=1;i < dfaRecord.baseState.size();i++)
    {
        headers.push_back(QString::fromStdString(dfaRecord.baseState[i].regular_Expression));
    }
    tableWidgit->setHorizontalHeaderLabels(headers);

    QStringList rowTags;
    for(int i =0 ;i<tableWidgit->rowCount();i++)
    {
        rowTags.push_back(QString("Row %1").arg(i+1));
    }
    tableWidgit->setVerticalHeaderLabels(rowTags);

    int rowi = 0;
    // 遍历行
    for (auto p : dfaRecord.state_DFA)
    {
        int colj = 0;
        string valueStart = to_string(p.first);
        QTableWidgetItem *itemStart = new QTableWidgetItem(QString::fromStdString(valueStart));
        tableWidgit->setItem(rowi, colj, itemStart);
        colj+=1;

        // 起点判断
        if(dfaRecord.startState.find(p.first)!=dfaRecord.startState.end())
        {
            QString stemp = QString("Row %1").arg(rowi+1)+":起点";
            rowTags[rowi] = stemp;
            tableWidgit->setVerticalHeaderLabels(rowTags);
        }
        // 终点判断
        if(dfaRecord.endState.find(p.first)!=dfaRecord.endState.end())
        {
            QString stemp = QString("Row %1").arg(rowi+1)+":终点";
            rowTags[rowi] = stemp;
            tableWidgit->setVerticalHeaderLabels(rowTags);
        }

        // 遍历列-可以走的每一条边
        for (int i = 1; i < dfaRecord.baseState.size(); i++)
        {
            string value;
            string re_tmp = dfaRecord.baseState[i].regular_Expression;
            value = to_string(p.second[re_tmp]);
            //            std::cout<<"setDFA" <<value<<std::endl;
            QTableWidgetItem *item = new QTableWidgetItem(QString::fromStdString(value));
            tableWidgit->setItem(rowi, colj, item);
            colj++;
        }
        rowi++;
    }
}



// 此函数调用了核心算法
void MainWindow::generateLalrAndShow()
{
    if (productionFilePath.isEmpty()) {
        QMessageBox::warning(this, tr("Error"), tr("你需要打开一个文件才能进行生成！"));
        return;
    }

    // 执行线程和等待窗口
    LalrWorker *worker = new LalrWorker();
    QProgressDialog *progressDialog = new QProgressDialog("你可能需要等待几秒，Please wait...", "Cancel", 0, 0, this);
    progressDialog->setWindowModality(Qt::WindowModal);
    QObject::connect(worker, &LalrWorker::progress, progressDialog, &QProgressDialog::setValue);
    QObject::connect(worker, &LalrWorker::finished, progressDialog, &QProgressDialog::accept);
    QObject::connect(progressDialog, &QProgressDialog::canceled, worker, &LalrWorker::terminate);

    // 执行任务
    QObject::connect(worker, &QThread::started, [&]() {
        // 调用算法执行
        QCoreApplication::processEvents();
        // 处理用户通过复选框选择的文法名称
        processAttributeNameBox();
        // 设置文法名称
//        this->lalrAlgor.productionsName = atrributeNameBox->currentText().toStdString();
        this->lalrAlgor.productionsName = string(atrributeNameBox->currentText().toLocal8Bit());
        this->lalrAlgor.processGenerateDfaAndAnalyseSheet(string(productionFilePath.toLocal8Bit()));
        emit finished_lalr();
    });

    worker->start();
    progressDialog->exec();

    qDebug()<<"lalr over it";
    // 显示输出的编码文件
    buildLalrDfaTableWidgitAndSheet();
}


void MainWindow::buildLalrDfaTableWidgitAndSheet()
{
    try {
        productionsTable->clear();
        firstSetTable->clear();
        followSetTable->clear();
        LR_DFA_Table->clear();
        LALR_DFA_Table->clear();
        analyseSheetTable->clear();

        productionsTableSetUp();
        firstSetTableSetUp();
        followSetTableSetUp();
        LR_DFA_TableSetUp();
        LALR_DFA_TableSetUp();
        analyseSheetTableSetUp();
    }
    catch(PRODUCTIONS_SENTENCE_ERROR)
    {
        QString msg = QString::fromStdString(PRODUCTIONS_SENTENCE_ERROR().message);
        QMessageBox::warning(this, tr("Error"),msg);
    }
    catch (...) {
        QString msg = QString("Unknown Error happened, please Check you PC is work well");
        QMessageBox::warning(this, tr("Error"),msg);
    }

}


void MainWindow::productionsTableSetUp()
{
    // 需要留意一下常引用的弊端
    ProductionUtil &productionUtil1 = lalrAlgor.lalrUtil1.ProductionUtil1;

    // 基本信息
    this->productionsTable->setColumnCount(1);
    this->productionsTable->setRowCount(productionUtil1.productions.size());
    // 列头
    QStringList headers;
    headers.push_back(QString("文法规则"));
    productionsTable->setHorizontalHeaderLabels(headers);

    QStringList rowTags;
    for(int i=0;i<productionUtil1.productions.size();i++)
    {
        QString stemp = QString("productionId: %1").arg(i);
        rowTags.push_back(stemp);
    }
    productionsTable->setVerticalHeaderLabels(rowTags);

    for(int i=0;i<productionUtil1.productions.size();i++)
    {
        string res = productionUtil1.productions[i].left+" -> "+ productionUtil1.productions[i].rightToString();
        QTableWidgetItem *item = new QTableWidgetItem(QString::fromStdString(res));
        productionsTable->setItem(i, 0, item);
    }
}

void MainWindow::firstSetTableSetUp()
{

    ProductionUtil &productionUtil1 = lalrAlgor.lalrUtil1.ProductionUtil1;
    // 设置表的大小
    this->firstSetTable->setColumnCount(1);
    this->firstSetTable->setRowCount(productionUtil1.productionLefts.size());


    QStringList headers;
    headers.push_back(QString("first集合"));
    firstSetTable->setHorizontalHeaderLabels(headers);

    QStringList rowTags;
    for(string left : productionUtil1.productionLefts)
    {
        QString stemp = QString::fromStdString(left);
        rowTags.push_back(stemp);
        //        qDebug()<<stemp;
    }
    firstSetTable->setVerticalHeaderLabels(rowTags);
    // 设置内容
    int row = 0;
    for(string left : productionUtil1.productionLefts)
    {
        set<string> si = productionUtil1.firstSet[left];
        QTableWidgetItem *item = new QTableWidgetItem(QString::fromStdString(setToString(si)));
        firstSetTable->setItem(row, 0, item);
        row++;
    }
}

void MainWindow::followSetTableSetUp()
{
    // 引用，减少调用层级
    ProductionUtil &productionUtil1 = lalrAlgor.lalrUtil1.ProductionUtil1;

    // 设置表的大小
    this->followSetTable->setColumnCount(1);
    this->followSetTable->setRowCount(productionUtil1.productionLefts.size());


    QStringList headers;
    headers.push_back(QString("first集合"));
    followSetTable->setHorizontalHeaderLabels(headers);

    QStringList rowTags;
    for(string left : productionUtil1.productionLefts)
    {
        QString stemp = QString::fromStdString(left);
        rowTags.push_back(stemp);
        //        qDebug()<<stemp;
    }
    followSetTable->setVerticalHeaderLabels(rowTags);
    // 设置内容
    int row = 0;
    for(string left : productionUtil1.productionLefts)
    {
        set<string> si = productionUtil1.followSet[left];
        QTableWidgetItem *item = new QTableWidgetItem(QString::fromStdString(setToString(si)));
        followSetTable->setItem(row, 0, item);
        row++;
    }
}

void MainWindow::LR_DFA_TableSetUp()
{
    LALR& lalrUtil1 = lalrAlgor.lalrUtil1;
    // 设置表的大小
    this->LR_DFA_Table->setRowCount(lalrUtil1.DFA_item_s.size());
    this->LR_DFA_Table->setColumnCount(lalrUtil1.analyseSheetHeader.size());

    // 这个记录了所有的可能的边

    QStringList columnTags;
    for (int i = 0; i < lalrUtil1.analyseSheetHeader.size(); i++)
    {
        QString stemp = QString::fromStdString(lalrUtil1.analyseSheetHeader[i].value);
        columnTags.push_back(stemp);
    }
    LR_DFA_Table->setHorizontalHeaderLabels(columnTags);

    // 行头

    QStringList rowTags;
    for (size_t i = 0; i <  lalrUtil1.DFA_item_s.size(); i++)
    {
        QString stemp = QString("nodeId: %1").arg(lalrUtil1.DFA_item_s[i].id);
        rowTags.push_back(stemp);
    }
    LR_DFA_Table->setVerticalHeaderLabels(rowTags);

    for (size_t i = 0; i < lalrUtil1.DFA_item_s.size(); i++)
    {
        int currId = lalrUtil1.DFA_item_s[i].id;
        if(lalrUtil1.DFA.find(currId)==lalrUtil1.DFA.end())
        {
            continue;
        }
        for (size_t j = 0; j < lalrUtil1.analyseSheetHeader.size(); j++)
        {
            string currEdge = lalrUtil1.analyseSheetHeader[j].value;
            if(lalrUtil1.DFA[currId].find(currEdge)==lalrUtil1.DFA[currId].end())
            {
                continue;
            }
            int nextId = lalrUtil1.DFA[currId][currEdge];
            QTableWidgetItem *item = new QTableWidgetItem(QString("id:%1").arg(nextId));
            LR_DFA_Table->setItem(i, j, item);
        }
    }


    //对DFA的Item的表格的设置
    LR_DFA_item_Table->clear();
    for(size_t i = 0;i<lalrUtil1.DFA_item_s.size();i++)
    {
        QTreeWidgetItem *baseItem= new QTreeWidgetItem(LR_DFA_item_Table);
        baseItem->setText(0, QString("nodeId: %1").arg(lalrUtil1.DFA_item_s[i].id)); // 设置根节点文本
        for(size_t j=0;j<lalrUtil1.DFA_item_s[i].items.size();j++)
        {
            QTreeWidgetItem *sonItem= new QTreeWidgetItem(baseItem);
            sonItem->setText(0, QString::fromStdString(lalrUtil1.DFA_item_s[i].items[j].toString())); // 设置根节点文本
        }
    }
    LR_DFA_item_Table->expandAll();
}



void MainWindow::LALR_DFA_TableSetUp()
{
    LALR& lalrUtil1 = lalrAlgor.lalrUtil1;

    // 设置表的大小
    this->LALR_DFA_Table->setRowCount(lalrUtil1.DFA_item_s_LALR_ordered.size());
    this->LALR_DFA_Table->setColumnCount(lalrUtil1.analyseSheetHeader.size());

    // 这个记录了所有的可能的边

    QStringList columnTags;
    for (size_t i = 0; i < lalrUtil1.analyseSheetHeader.size(); i++)
    {
        QString stemp = QString::fromStdString(lalrUtil1.analyseSheetHeader[i].value);
        columnTags.push_back(stemp);
    }
    LALR_DFA_Table->setHorizontalHeaderLabels(columnTags);

    // 行头

    QStringList rowTags;
    for (size_t i = 0; i <  lalrUtil1.DFA_item_s_LALR_ordered.size(); i++)
    {
        QString stemp = QString("nodeId: %1").arg(lalrUtil1.DFA_item_s_LALR_ordered[i].id);
        rowTags.push_back(stemp);
    }
    LALR_DFA_Table->setVerticalHeaderLabels(rowTags);

    for (size_t i = 0; i <  lalrUtil1.DFA_item_s_LALR_ordered.size(); i++)
    {
        int currId = lalrUtil1.DFA_item_s_LALR_ordered[i].id;
        if(lalrUtil1.DFA_LALR_ordered.find(currId)==lalrUtil1.DFA_LALR_ordered.end())
        {
            continue;
        }
        for (size_t j = 0; j < lalrUtil1.analyseSheetHeader.size(); j++)
        {
            string currEdge = lalrUtil1.analyseSheetHeader[j].value;
            if(lalrUtil1.DFA_LALR_ordered[currId].find(currEdge)==lalrUtil1.DFA_LALR_ordered[currId].end())
            {
                continue;
            }
            int nextId = lalrUtil1.DFA_LALR_ordered[currId][currEdge];
            QTableWidgetItem *item = new QTableWidgetItem(QString("id:%1").arg(nextId));
            LALR_DFA_Table->setItem(i, j, item);
        }
    }



    //对LALR_DFA的Item的表格的设置
    LALR_DFA_item_WidgetTable->clear();
    // 确认item的行数
    for(size_t i = 0;i<lalrUtil1.DFA_item_s_LALR_ordered.size();i++)
    {
        QTreeWidgetItem *baseItem= new QTreeWidgetItem(LALR_DFA_item_WidgetTable);
        baseItem->setText(0, QString("nodeId: %1").arg(lalrUtil1.DFA_item_s_LALR_ordered[i].id)); // 设置根节点文本
        for(size_t j=0;j<lalrUtil1.DFA_item_s_LALR_ordered[i].items.size();j++)
        {
            QTreeWidgetItem *sonItem= new QTreeWidgetItem(baseItem);
            sonItem->setText(0, QString::fromStdString(lalrUtil1.DFA_item_s_LALR_ordered[i].items[j].toString())); // 设置根节点文本
        }
    }
    LALR_DFA_item_WidgetTable->expandAll();
}

void MainWindow::analyseSheetTableSetUp()
{
        LALR& lalrUtil1 = lalrAlgor.lalrUtil1;

    // 设置表的大小
    this->analyseSheetTable->setRowCount(lalrUtil1.DFA_item_s_LALR_ordered.size());
    this->analyseSheetTable->setColumnCount(lalrUtil1.analyseSheetHeader.size());

    // 这个记录了所有的可能的边

    QStringList columnTags;
    for (size_t i = 0; i < lalrUtil1.analyseSheetHeader.size(); i++)
    {
        QString stemp = QString::fromStdString(lalrUtil1.analyseSheetHeader[i].value);
        columnTags.push_back(stemp);
    }
    analyseSheetTable->setHorizontalHeaderLabels(columnTags);

    // 行头

    QStringList rowTags;
    for (size_t i = 0; i <  lalrUtil1.DFA_item_s_LALR_ordered.size(); i++)
    {
        QString stemp = QString("NodeId: %1").arg(lalrUtil1.DFA_item_s_LALR_ordered[i].id);
        rowTags.push_back(stemp);
    }
    analyseSheetTable->setVerticalHeaderLabels(rowTags);

    for (size_t i = 0; i <  lalrUtil1.DFA_item_s_LALR_ordered.size(); i++)
    {
        int currId = lalrUtil1.DFA_item_s_LALR_ordered[i].id;
        if(lalrUtil1.DFA_LALR_ordered.find(currId)==lalrUtil1.DFA_LALR_ordered.end())
        {
            continue;
        }
        for (size_t j = 0; j < lalrUtil1.analyseSheetHeader.size(); j++)
        {
            string currEdge = lalrUtil1.analyseSheetHeader[j].value;
            SheetItem sItem = lalrUtil1.analyseSheet[currId][currEdge];
            QTableWidgetItem *item = new QTableWidgetItem(QString::fromStdString(sItem.toString()));
            analyseSheetTable->setItem(i, j, item);
        }
    }
}



void MainWindow::buildAnalyseRecord_Ast_AnalyseTree()
{
    buildAnalyseRecord();
    buildAst();
    buildAnalyseTree();
    buildFac();
    buildAformatStTree();
}

void MainWindow::buildAnalyseRecord()
{
    LALR& lalrUtil1 = lalrAlgor.lalrUtil1;

    lalrAnalyseRecordTableWidget->clear();


    // 设置表的大小
    this->lalrAnalyseRecordTableWidget->setRowCount(lalrUtil1.analyseRecordList.size());
    this->lalrAnalyseRecordTableWidget->setColumnCount(lalrUtil1.analyseRecordListColumns.size());

    QStringList columnTags;
    // 将分析表的列标记加入
    for (size_t i = 0; i < lalrUtil1.analyseRecordListColumns.size(); i++)
    {
        QString stemp = QString::fromStdString(lalrUtil1.analyseRecordListColumns[i]);
        columnTags.push_back(stemp);
    }
    lalrAnalyseRecordTableWidget->setHorizontalHeaderLabels(columnTags);

    // 行头

    QStringList rowTags;
    for (size_t i = 0; i <  lalrUtil1.analyseRecordList.size(); i++)
    {
        QString stemp = QString("LineId: %1").arg(lalrUtil1.analyseRecordList[i].lineId);
        rowTags.push_back(stemp);
    }
    lalrAnalyseRecordTableWidget->setVerticalHeaderLabels(rowTags);

    // 内容数据
    for (int i = 0; i < lalrUtil1.analyseRecordList.size(); i++) {

        analyseRecord& record =  lalrUtil1.analyseRecordList[i];
        std::cout<<"add:"<<record.getDetails()<<std::endl;

        QTableWidgetItem *item_statusStackStatus = new QTableWidgetItem(QString::fromStdString(record.statusStackStatus));
        lalrAnalyseRecordTableWidget->setItem(i, 0, item_statusStackStatus);

        QTableWidgetItem *item_characterStackStatus = new QTableWidgetItem(QString::fromStdString(record.characterStackStatus));
        lalrAnalyseRecordTableWidget->setItem(i, 1, item_characterStackStatus);

        QTableWidgetItem *item_inputQueueStatus = new QTableWidgetItem(QString::fromStdString(record.inputQueueStatus));
        lalrAnalyseRecordTableWidget->setItem(i, 2, item_inputQueueStatus);

        QTableWidgetItem *item_action = new QTableWidgetItem(QString::fromStdString(record.action));
        lalrAnalyseRecordTableWidget->setItem(i, 3, item_action);

        QTableWidgetItem *item_gotoContent = new QTableWidgetItem(QString::fromStdString(record.gotoContent));
        lalrAnalyseRecordTableWidget->setItem(i, 4, item_gotoContent);
    }
}

void MainWindow::buildAst(){
    this->lalrAstTreeWidget->clear();
    buildAstTreeNodes();
}

QTreeWidgetItem *MainWindow::buildAstTreeNodes()
{
    AstTreeNode* root =this->lalrAlgor.lalrUtil1.astTree.root;

    if (root == nullptr) {
        cout << "AST树节点为空" << endl;
        return nullptr;
        QMessageBox::information(this,"提示","此次不是minic或者tiny的分析，不支持抽象语法树");
    }
    try {
        QTreeWidgetItem *rootItem = new QTreeWidgetItem(lalrAstTreeWidget);
        rootItem->setExpanded(true);
        rootItem->setText(0, "start"); // 设置根节点文本
        buildAstTreeNodesSupport(rootItem, root, 0);

        return rootItem;
    } catch (...) {
        throw new AST_TREE_ERROR();
    }

    return nullptr;
}

QTreeWidgetItem *MainWindow::buildAstTreeNodesSupport(QTreeWidgetItem *root, AstTreeNode *astRoot, int depth)
{
    // 构造节点
    QTreeWidgetItem *item = new QTreeWidgetItem(root);
    string outputStr = astRoot->value;
    item->setText(0, QString::fromStdString(outputStr)); // 设置根节点文本
    item->setExpanded(true);

    cout << string(depth, '*') << astRoot->value << endl;
    for (int i = 0; i < astRoot->children.size(); i++) {
        AstTreeNode *childNode = astRoot->children[i];
        buildAstTreeNodesSupport(item, childNode, depth + 1);
    }
    return item;
}



void MainWindow::buildAnalyseTree(){
    lalrAnalyseTreeWidget->clear();
    buildAnalyseTreeNodes();
}

void MainWindow::buildFac()
{
    ui->lalrTupleTableWidget->clear();
    QTableWidget * tableWidget = ui->lalrTupleTableWidget;

    LALR& lalrUtil1 = lalrAlgor.lalrUtil1;
    FourthTupleList ftList =  lalrUtil1.formatAstTree.getTupleList();
    vector<FourthTuple> tupList =  ftList.getList();

    // 设置表的大小
    tableWidget->setRowCount(tupList.size());
    tableWidget->setColumnCount(4);// 四元组

    QStringList columnTags;
    // 将分析表的列标记加入
    for (size_t i = 0; i < ftList.getColTags().size(); i++)
    {
        QString stemp = QString::fromStdString(ftList.getColTags().at(i));
        columnTags.push_back(stemp);
    }
    tableWidget->setHorizontalHeaderLabels(columnTags);

    // 行头
    QStringList rowTags;
    for (size_t i = 0; i <  tupList.size(); i++)
    {
        QString stemp = QString::fromStdString(tupList[i].getLineId());
        rowTags.push_back(stemp);
    }
    tableWidget->setVerticalHeaderLabels(rowTags);

    // 内容数据
    for (int i = 0; i < tupList.size(); i++) {
        // 获取分析记录
        FourthTuple& record =  tupList[i];

        QTableWidgetItem *op = new QTableWidgetItem(QString::fromStdString(record.getOp()));
        tableWidget->setItem(i, 0, op);

        QTableWidgetItem *arg1 = new QTableWidgetItem(QString::fromStdString(record.getArg1()));
        tableWidget->setItem(i, 1, arg1);

        QTableWidgetItem *arg2 = new QTableWidgetItem(QString::fromStdString(record.getArg2()));
        tableWidget->setItem(i, 2, arg2);

        QTableWidgetItem *tag = new QTableWidgetItem(QString::fromStdString(record.getTag()));
        tableWidget->setItem(i, 3, tag);
    }
}

void MainWindow::buildAformatStTree()
{
   ui->lalrAformatStTreeWidget->clear();
    buildAformatStTreeNodes();
}

QTreeWidgetItem *MainWindow::buildAformatStTreeNodes()
{
    AstTreeNode* root =this->lalrAlgor.lalrUtil1.formatAstTree.getRoot();
    QTreeWidget *treeWidget = ui->lalrAformatStTreeWidget;

    if (root == nullptr) {
        cout << "AST树节点为空" << endl;
        return nullptr;
        QMessageBox::information(this,"提示","此次不是minic或者tiny的分析，不支持抽象语法树");
    }
    try {
        QTreeWidgetItem *rootItem = new QTreeWidgetItem(treeWidget);
        rootItem->setExpanded(true);
        rootItem->setText(0, "start"); // 设置根节点文本
        buildAformatStTreeNodesSupport(rootItem, root, 0);

        return rootItem;
    } catch (...) {
        throw new AST_TREE_ERROR();
    }

    return nullptr;
}

QTreeWidgetItem *MainWindow::buildAformatStTreeNodesSupport(QTreeWidgetItem *root, AstTreeNode *astRoot, int depth)
{
    // 构造节点
    QTreeWidgetItem *item = new QTreeWidgetItem(root);
    string outputStr = astRoot->value;
    item->setText(0, QString::fromStdString(outputStr)); // 设置根节点文本
    item->setExpanded(true);

    cout << string(depth, '*') << astRoot->value << endl;
    for (int i = 0; i < astRoot->children.size(); i++) {
        AstTreeNode *childNode = astRoot->children[i];
        buildAformatStTreeNodesSupport(item, childNode, depth + 1);
    }
    return item;
}


QTreeWidgetItem*  MainWindow::buildAnalyseTreeNodes()
{
    int rootId = lalrAlgor.lalrUtil1.tree1.rootId;
    if (rootId == -1) {
        cout << "根节点错误，请检测程序允许情况" << endl;
        return nullptr;
    }
    QTreeWidgetItem *rootItem = new QTreeWidgetItem(lalrAnalyseTreeWidget);
    rootItem->setExpanded(true);
    rootItem->setText(0, "start"); // 设置根节点文本
//    QTreeWidgetItem* root =
    buildAnalyseTreeNodesSupport(rootItem,rootId, 0);
}

QTreeWidgetItem *MainWindow::buildAnalyseTreeNodesSupport(QTreeWidgetItem *root, int rootId, int depth)
{
    LalrTreeNode rootNode = lalrAlgor.lalrUtil1.tree1.treeNodes[rootId];

    // 构造节点
    QTreeWidgetItem *item = new QTreeWidgetItem(root);
    string outputStr = rootNode.value;
    item->setText(0, QString::fromStdString(outputStr)); // 设置根节点文本
    item->setExpanded(true);
    cout << string(depth, '.') << outputStr << endl;
    for (int i = 0; i < rootNode.childs.size(); i++) {
        int childId = rootNode.childs[i];
        buildAnalyseTreeNodesSupport(item,childId, depth + 1);
    }
    return item;
}



